package com.demo.dbcompare.web;

import java.util.ArrayList;
import java.util.List;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.demo.dbcompare.enums.CompareConstant;
import com.demo.dbcompare.enums.DbType;
import com.demo.dbcompare.model.dto.CompareTastDto;
import com.demo.dbcompare.model.dto.ConnConf;
import com.demo.dbcompare.model.dto.TableDiff;
import com.demo.dbcompare.model.vo.CompareVo;
import com.demo.dbcompare.model.vo.DataGridVo;
import com.demo.dbcompare.model.vo.DbCompareDiffVo;
import com.demo.dbcompare.service.TableColumnInfoService;


@RestController
public class CompareController {
	private static final Logger logger = LoggerFactory.getLogger(CompareController.class);
	@Autowired
	private TableColumnInfoService tableColumnInfoService;
	
	@RequestMapping(value="/compare")
	public DataGridVo<DbCompareDiffVo> compare(CompareVo vo,
			@RequestParam(value="diffFlag", defaultValue="1")boolean diffFlag,
			@RequestParam(value="page", defaultValue="1")int pageNumber,
			@RequestParam(value="rows", defaultValue="100")int pageSize){
		DataGridVo<DbCompareDiffVo> dataGridDto = new DataGridVo<>();
		if (StringUtils.isBlank(vo.getUrlLeft()) || StringUtils.isBlank(vo.getUrlRight())) {
			return dataGridDto;
		}
		try {
			CompareTastDto compareTast = genCompareTast(vo);
			compareTast.setTableColumnInfoListLeft(tableColumnInfoService.seizeTableColumnInfo(compareTast, CompareConstant.DEFAULT_LEFT_CONN_NAME));
			compareTast.setTableColumnInfoListRight(tableColumnInfoService.seizeTableColumnInfo(compareTast, CompareConstant.DEFAULT_RIGHT_CONN_NAME));
			List<DbCompareDiffVo> diffList = new ArrayList<>();
			if (diffFlag) {
				diffList.addAll(new TableDiff().genDiff(
						compareTast.getConnNameLeft(),
						compareTast.getConnNameRight(),
						compareTast.getTableNameListLeft(), 
						compareTast.getTableNameListRight(),
						compareTast.getTableColumnInfoListLeft(),
						compareTast.getTableColumnInfoListRight()));
			}else {
				diffList.addAll(new TableDiff().genSimilarities(
						compareTast.getConnNameLeft(),
						compareTast.getConnNameRight(),
						compareTast.getTableNameListLeft(), 
						compareTast.getTableNameListRight(),
						compareTast.getTableColumnInfoListLeft(),
						compareTast.getTableColumnInfoListRight()));
			}

			dataGridDto.setTotal(diffList.size());
			int fromIndex = ((pageNumber >= 1 ? pageNumber : 1) - 1) * pageSize;
			int toIndex = Math.min(fromIndex + pageSize, diffList.size());
			dataGridDto.setRows(diffList.subList(fromIndex, toIndex));
		} catch (Exception e) {
			logger.error("获取比较结果发生异常", e);
		}
		return dataGridDto;
	}

	/**
	 * CompareVo转CompareTastDto
	 * @param vo
	 * @return
	 * @author: jie.deng
	 * @time: 2018年1月11日 下午4:41:54
	 */
	public CompareTastDto genCompareTast(CompareVo vo) {
		CompareTastDto compareTast = new CompareTastDto();
		// 1.connName赋值
		compareTast.setConnNameLeft(
				StringUtils.isBlank(vo.getConnNameLeft()) ? CompareConstant.DEFAULT_LEFT_CONN_NAME : vo.getConnNameLeft());
		compareTast.setConnNameRight(
				StringUtils.isBlank(vo.getConnNameRight()) ? CompareConstant.DEFAULT_RIGHT_CONN_NAME : vo.getConnNameRight());

		// 2.dbName根据url和username计算得到
		String urlLeft = vo.getUrlLeft();
		if (DbType.fromUrl(urlLeft) == DbType.Oracle) {
			compareTast.setDbNameLeft(vo.getUsernameLeft().toUpperCase());
		} else if (DbType.fromUrl(urlLeft) == DbType.MySQL) {
			if (urlLeft.indexOf('?') == -1) {
				compareTast.setDbNameLeft(urlLeft.substring(urlLeft.lastIndexOf('/') + 1).toUpperCase());
			} else {
				compareTast.setDbNameLeft(urlLeft.substring(urlLeft.lastIndexOf('/') + 1, urlLeft.indexOf('?')).toUpperCase());
			}
		}
		String urlRight = vo.getUrlRight();
		if (DbType.fromUrl(urlRight) == DbType.Oracle) {
			compareTast.setDbNameRight(vo.getUsernameRight().toUpperCase());
		} else if (DbType.fromUrl(vo.getUrlRight()) == DbType.MySQL) {
			if (urlRight.indexOf('?') == -1) {
				compareTast.setDbNameRight(urlRight.substring(urlRight.lastIndexOf('/') + 1).toUpperCase());
			} else {
				compareTast.setDbNameRight(urlRight.substring(urlRight.lastIndexOf('/') + 1, urlRight.indexOf('?')).toUpperCase());
			}
		}

		// 3.tableName转为大写格式
		List<String> tableNameListLeft = vo.getTableNameListLeft();
		if (CollectionUtils.isNotEmpty(tableNameListLeft)) {
			List<String> list = new ArrayList<>();
			for (String str : tableNameListLeft) {
				if (null != str) {
					list.add(str.toUpperCase().trim());
				}
			}
			// 如果最后一个元素是null或者空字符串，则循环删除
			int endIndex = list.size() - 1;
			while (CollectionUtils.isNotEmpty(list) && StringUtils.isBlank(list.get(endIndex))) {
				list.remove(endIndex);
				endIndex--;
			}
			compareTast.setTableNameListLeft(list);
		}
		List<String> tableNameListRight = vo.getTableNameListRight();
		if (CollectionUtils.isNotEmpty(tableNameListRight)) {
			List<String> list = new ArrayList<>();
			for (String str : tableNameListRight) {
				if (null != str) {
					list.add(str.toUpperCase().trim());
				}
			}
			// 如果最后一个元素是null或者空字符串，则循环删除
			int endIndex = list.size() - 1;
			while (CollectionUtils.isNotEmpty(list) && StringUtils.isBlank(list.get(endIndex))) {
				list.remove(endIndex);
				endIndex--;
			}
			compareTast.setTableNameListRight(list);
		}
			 
		// 设置左右连接
		compareTast.setConnConfLeft(genConnConf(vo, CompareConstant.DEFAULT_LEFT_CONN_NAME));
		compareTast.setConnConfRight(genConnConf(vo, CompareConstant.DEFAULT_RIGHT_CONN_NAME));
		return compareTast;
	}
	
	private ConnConf genConnConf(CompareVo vo, String connName) {
		if (connName.equals(CompareConstant.DEFAULT_LEFT_CONN_NAME)) {
			String url = vo.getUrlLeft();
			String username = vo.getUsernameLeft();
			String password = vo.getPasswordLeft();
			String driver = DbType.fromUrl(url).getDriver();
			return new ConnConf(driver, url, username, password);
		} else if (connName.equals(CompareConstant.DEFAULT_RIGHT_CONN_NAME)) {
			String url = vo.getUrlRight();
			String username = vo.getUsernameRight();
			String password = vo.getPasswordRight();
			String driver = DbType.fromUrl(url).getDriver();
			return new ConnConf(driver, url, username, password);
		}
		return new ConnConf();
	}

}
